package com.tyf.esClient.controller;


import com.alibaba.fastjson.JSON;
import com.tyf.common.utils.R;
import com.tyf.esClient.model.User;
import jakarta.annotation.Resource;
import org.elasticsearch.action.DocWriteResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/esClientStudent")
public class StudentClientEsController {

    @Resource
    private RestHighLevelClient client;

    @GetMapping("/createIndex")
    public R createIndex(String indexName) throws IOException {

        // 定义索引的基本配置
        Settings settings = Settings.builder()
                .put("index.number_of_shards", 1) // 分片数量，默认为1
                .put("index.number_of_replicas", 1) // 副本数量，默认为1
                .build();

        // 创建CreateIndexRequest对象
        CreateIndexRequest request = new CreateIndexRequest(indexName);
        request.settings(settings);

        // 设置索引的映射（mapping），如果需要的话
        request.mapping(createMapping());

        // 使用RestHighLevelClient执行请求
        CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT);

        // 检查响应以确认索引是否成功创建
        if (response.isAcknowledged()) {
            System.out.println("索引 [" + indexName + "] 已成功创建");
        } else {
            System.out.println("索引 [" + indexName + "] 创建请求未被确认");
        }
        return R.ok();
    }

    /**
     * esClient 构建查询请求
     * @param user
     * @return
     * @throws IOException
     */
    @RequestMapping("/getList")
    public R getList(User user) throws IOException {
        // 构建搜索请求
        SearchRequest searchRequest = new SearchRequest("user");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        // 添加查询条件，这里使用match_all查询来获取所有文档
        searchSourceBuilder.query(QueryBuilders.matchAllQuery());

        // 多条件查询
//        searchSourceBuilder.query(
//                QueryBuilders.boolQuery()
//                        .must(QueryBuilders.matchQuery("field1", "value1")) // 必须满足的条件
//                        .should(QueryBuilders.matchQuery("field2", "value2"))
//                        .should(QueryBuilders.matchQuery("field3", "value3"))// 可以满足的一个或多个条件
//        );

        // 设置分页、排序或其他搜索选项（如果需要）
        searchSourceBuilder.from(0).size(10); // 获取前10条记录

        searchRequest.source(searchSourceBuilder);

        // 执行搜索请求
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);

        // 处理响应结果
        for (SearchHit hit : searchResponse.getHits()) {
            System.out.println(hit.getSourceAsString());
        }
        return R.ok();
    }

    @PostMapping("/save")
    public R save(@RequestBody User user) throws IOException {
        // 创建IndexRequest对象，设置索引名和文档ID
        IndexRequest request = new IndexRequest("user");
//        if (documentId != null) {
//            request.id(documentId); // 如果你有一个特定的文档ID要使用
//        }

        // 将数据转换为JSON格式并填充到请求体中
        request.source(JSON.toJSON(user), XContentType.JSON);

        // 执行插入操作
        IndexResponse response = client.index(request, RequestOptions.DEFAULT);

        // 检查响应以确认操作是否成功
        if (response.getResult() == DocWriteResponse.Result.CREATED || response.getResult() == DocWriteResponse.Result.UPDATED) {
            System.out.println("文档已成功添加或更新，版本号: " + response.getVersion());
        } else {
            System.out.println("添加文档失败");
        }
        return R.ok();
    }

    @PostMapping("/edit")
    public R edit(@RequestBody User user) throws IOException {


//        String indexName = "your_index";
//        String documentId = "1"; // 文档ID
        Map<String, Object> updatedFieluds = new HashMap<>();
        updatedFieluds.put("JSON", JSON.toJSON(user)); // 更新字段及其新值

        // 创建UpdateRequest对象
        UpdateRequest updateRequest = new UpdateRequest("user", user.getUserId())
                .doc(updatedFieluds); // 如果只是简单地更新某些字段，则使用.doc方法

        // 如果需要执行脚本更新，可以使用.script方法
        // Script script = ...; // 创建或获取Script对象
        // updateRequest.script(script);

        // 执行更新操作
        try {
            UpdateResponse updateResponse = client.update(updateRequest, RequestOptions.DEFAULT);
            if (updateResponse.getResult() == DocWriteResponse.Result.UPDATED) {
                System.out.println("Document was successfully updated.");
            } else {
                System.out.println("Document update failed or the document did not exist.");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return R.ok();
    }

    // 创建XContentBuilder以定义索引的映射（mapping）
    private static XContentBuilder createMapping() throws IOException {
        return XContentBuilder.builder(JsonXContent.jsonXContent)
                .startObject()
                    .startObject("properties")
                        .startObject("user_id").field("type", "keyword").endObject()
                        .startObject("userName").field("type", "keyword").endObject()
                        .startObject("phone").field("type", "keyword").endObject()
                    // 更多字段和设置...
                    .endObject()
                .endObject();
    }

}
